
<template>
  <h2>关系图谱</h2> 
  <!-- <button @click="go">Go</button> -->
  <div class="graph" id="graph"></div>
</template>

<script setup>
import * as d3 from "d3"
import graph from './json'

function go() {
  const width = 600, height = 400;
  const color = d3.scaleOrdinal(d3.schemeCategory10);
  const types = ["CITED_BY"]

  const strokeWidth = '1'

  const simulation = d3.forceSimulation(graph.nodes)
    .force("charge", d3.forceManyBody().strength(-3000))
    .force("x", d3.forceX(width / 2).strength(1))
    .force("y", d3.forceY(height / 2).strength(1))
    .force("link", d3.forceLink(graph.links).id(function (d) { return d.id; }).distance(300).strength(1))
    .on("tick", ticked)

  const svg = d3.select("#graph").append("svg")
    .attr("width", width).attr("height", height)
    .attr("pointer-events", "all");

  // Per-type markers, as they don't inherit styles.
  svg.append("defs").selectAll("marker")
    .data(types)
    .join("marker")
    .attr("id", d => `arrow-${d}`)
    .attr("viewBox", "0 0 10 10")
    .attr("refX", 10)
    .attr("refY", 5)
    .attr("markerUnits", strokeWidth)
    .attr("markerWidth", 20)
    .attr("markerHeight", 20)
    .attr("orient", "auto")
    .append("path")
    .attr("fill", color)
    .attr("d", 'M 0 0 L 10 5 L 0 10 z');

  const link = svg.append("g")
    .selectAll("g")
    .data(graph.links)
    .enter()
    .append("line")
    .attr("stroke", d => color(d.type))
    .attr("stroke-width", strokeWidth)
    .attr("marker-end", d => `url(${new URL(`#arrow-${d.type}`, location)})`);

  const node = svg.append("g")
    .selectAll("g")
    .data(graph.nodes)
    .enter().append("g");

  // node.append("circle")
  //   .attr("r", 40)
  //   .attr("fill", function (d) { return color(d.label); })

  var blues = d3.scaleOrdinal(d3.schemeBlues[6]);
  node.append("circle")
    .attr("r", 40)
    .attr("fill", function (d, i) {
      return blues(i);
    })

  node.call(
    d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended)
  );
  node.append("text")
    .text(function (d) {
      return d.id;
    })
    .attr('x', -50)
    .attr('y', 3).style('fill', 'blue');

  node.append("title")
    .text(function (d) { return d.label; });

  function ticked() {

    node.call(updateNode);
    link.call(updateLink);

  }

  function fixna(x) {
    if (isFinite(x)) return x;
    return 0;
  }

  function updateLink(link) {
    link.attr("x1", function (d) { return fixna(d.source.x); })
      .attr("y1", function (d) { return fixna(d.source.y); })
      .attr("x2", function (d) { return fixna(d.target.x); })
      .attr("y2", function (d) { return fixna(d.target.y); });
  }

  function updateNode(node) {
    node.attr("transform", function (d) {
      return "translate(" + fixna(d.x) + "," + fixna(d.y) + ")";
    });
  }

  function dragstarted(event, d) {
    event.sourceEvent.stopPropagation();
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  function dragged(event, d) {
    d.fx = event.x;
    d.fy = event.y;
  }

  function dragended(event, d) {
    if (!event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }

  function clicked(event, d) {
    console(event, d)
  }

  // });
}

import { onMounted } from 'vue'
onMounted(() => {
  go()
})


</script>


